﻿using System;
using Birkelund.QueryStrings;
using NUnit.Framework;
using System.Reflection;

namespace Birkelund.QueryStrings.Test
{
    public class FailureArgsTest
    {
        [Test]
        public void ConstructorTest1()
        {
            string key = "key";
            string attemptedValue = "attemptedValue";
            Uri fullUrl = new Uri("http://www.test.dk");
            FailureReason cause = FailureReason.TokenDoesNotExist;
            Exception exception = new Exception("innerException");
            Type expectedType = typeof(int);

            FailureArgs args = new FailureArgs(key, attemptedValue, fullUrl, cause, expectedType, exception);
            Assert.AreEqual(key, args.KeyName);
            Assert.AreEqual(attemptedValue, args.Value);
            Assert.AreEqual(fullUrl, args.FullUri);
            Assert.AreEqual(cause, args.Reason);
            Assert.AreEqual(expectedType, args.ExpectedType);
            Assert.AreEqual(exception, args.Exception);
        }

        [Test]
        public void ConstructorTest2()
        {
            string key = "key";
            string attemptedValue = "attemptedValue";
            Uri fullUrl = new Uri("http://www.test.dk");
            FailureReason cause = FailureReason.ParseError;
            Type expectedType = typeof(int);

            FailureArgs args = new FailureArgs(key, attemptedValue, fullUrl, cause, expectedType);
            Assert.AreEqual(key, args.KeyName);
            Assert.AreEqual(attemptedValue, args.Value);
            Assert.AreEqual(fullUrl, args.FullUri);
            Assert.AreEqual(cause, args.Reason);
            Assert.AreEqual(expectedType, args.ExpectedType);
            Assert.IsNull(args.Exception);
        }

        [Test]
        public void ToStringTest_TypeIsNull()
        {
            FailureArgs args = new FailureArgs(string.Empty, string.Empty, null, default(FailureReason), null);
            string toString = args.ToString();
            StringAssert.DoesNotContain("ExpectedType", toString); //verify that the type informationis not printed
        }

        [Test]
        public void ToStringTest_ExceptionIsNull()
        {
            FailureArgs args = new FailureArgs(string.Empty, string.Empty, null, default(FailureReason), typeof(string), null);
            string toString = args.ToString();
            StringAssert.DoesNotContain("Exception", toString); //verify that the exception message is not printed
        }

        [Test]
        public void ToStringTest_NoneIsNull()
        {
            FailureArgs args = new FailureArgs(string.Empty, string.Empty, null, default(FailureReason), typeof(string), new ArgumentException("My exception"));
            string toString = args.ToString();
            StringAssert.Contains("Exception", toString); 
            StringAssert.Contains("ExpectedType", toString);
        }

        [TestCase("hello", Result = "hello", TestName = "String")]
        [TestCase(null, Result = "null", TestName = "Null")]
        //ought to Test Exception too - cannot to this with attribute syntax
        public string NullIfNullTest(object input)
        {
            BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod;
            const string METHOD_NAME = "NullIfNull";

            return
                typeof(FailureArgs).InvokeMember(METHOD_NAME, flags, null, null, new object[] { input }) as string;
        }
    }
}
